home *** CD-ROM | disk | FTP | other *** search
/ Aminet 16 / Aminet 16 (1996)(GTI - Schatztruhe)[!][Dec 1996].iso / Aminet / comm / term / term_source.lha / Extras / Source / term-source.lha / Serial.c < prev    next >
C/C++ Source or Header  |  1996-10-20  |  26KB  |  1,332 lines

  1. /*
  2. **    Serial.c
  3. **
  4. **    Serial driver support routines
  5. **
  6. **    Copyright © 1990-1996 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. **
  9. **    :ts=4
  10. */
  11.  
  12. #ifndef _GLOBAL_H
  13. #include "Global.h"
  14. #endif
  15.  
  16.     /* In case the DSR test is enabled */
  17.  
  18. STATIC BOOL UseRTS_CTS;
  19.  
  20.     /* Serial write output routines */
  21.  
  22. STATIC SERWRITE SerWriteRoutine,SerWriteAndProcessRoutine;
  23.  
  24. STATIC VOID
  25. WriteAndProcessUserMon(APTR Buffer,LONG Size)
  26. {
  27.     Size = XProtocolUserMon(XprIO,Buffer,Size,Size);
  28.  
  29.     if(Size > 0)
  30.     {
  31.         StartSerialWrite(Buffer,Size);
  32.  
  33.         if(Marking)
  34.             WindowMarkerStop();
  35.  
  36.         ConProcess(Buffer,Size);
  37.  
  38.         WaitSerialWrite();
  39.  
  40.         BytesOut += Size;
  41.     }
  42. }
  43.  
  44. STATIC VOID
  45. WriteUserMon(APTR Buffer,LONG Size)
  46. {
  47.     Size = XProtocolUserMon(XprIO,Buffer,Size,Size);
  48.  
  49.     if(Size > 0)
  50.     {
  51.         DoSerialWrite(Buffer,Size);
  52.  
  53.         BytesOut += Size;
  54.     }
  55. }
  56.  
  57. STATIC VOID
  58. WriteAndProcessBypass(APTR Buffer,LONG Size)
  59. {
  60.     if((*SerWriteBypass)(Buffer,Size))
  61.     {
  62.         StartSerialWrite(Buffer,Size);
  63.  
  64.         ConProcess(Buffer,Size);
  65.  
  66.         WaitSerialWrite();
  67.  
  68.         BytesOut += Size;
  69.     }
  70. }
  71.  
  72. STATIC VOID
  73. WriteBypass(APTR Buffer,LONG Size)
  74. {
  75.     if((*SerWriteBypass)(Buffer,Size))
  76.     {
  77.         DoSerialWrite(Buffer,Size);
  78.  
  79.         BytesOut += Size;
  80.     }
  81. }
  82.  
  83. STATIC VOID
  84. WriteAndProcessBypassUserMon(APTR Buffer,LONG Size)
  85. {
  86.     if((*SerWriteBypass)(Buffer,Size))
  87.     {
  88.         Size = XProtocolUserMon(XprIO,Buffer,Size,Size);
  89.  
  90.         if(Size > 0)
  91.         {
  92.             StartSerialWrite(Buffer,Size);
  93.  
  94.             ConProcess(Buffer,Size);
  95.  
  96.             WaitSerialWrite();
  97.  
  98.             BytesOut += Size;
  99.         }
  100.     }
  101. }
  102.  
  103. STATIC VOID
  104. WriteBypassUserMon(APTR Buffer,LONG Size)
  105. {
  106.     if((*SerWriteBypass)(Buffer,Size))
  107.     {
  108.         Size = XProtocolUserMon(XprIO,Buffer,Size,Size);
  109.  
  110.         if(Size > 0)
  111.         {
  112.             DoSerialWrite(Buffer,Size);
  113.  
  114.             BytesOut += Size;
  115.         }
  116.     }
  117. }
  118.  
  119.     /* WriteAndProcess(APTR Buffer,LONG Size):
  120.      *
  121.      *    At the same time write data to the serial port and
  122.      *    process it on the screen.
  123.      */
  124.  
  125. STATIC VOID
  126. WriteAndProcess(APTR Buffer,LONG Size)
  127. {
  128.     StartSerialWrite(Buffer,Size);
  129.  
  130.     ConProcess(Buffer,Size);
  131.  
  132.     WaitSerialWrite();
  133.  
  134.     BytesOut += Size;
  135. }
  136.  
  137.     /* WriteDirect(APTR Buffer,LONG Size):
  138.      *
  139.      *    Output the data and update the byte counter.
  140.      */
  141.  
  142. STATIC VOID
  143. WriteDirect(APTR Buffer,LONG Size)
  144. {
  145.     DoSerialWrite(Buffer,Size);
  146.  
  147.     BytesOut += Size;
  148. }
  149.  
  150.     /* SetFlags():
  151.      *
  152.      *    Set the contents of a serial device request according
  153.      *    to the current configuration settings.
  154.      */
  155.  
  156. STATIC BYTE
  157. SetFlags(VOID)
  158. {
  159.     return(SetBothSerialAttributes(
  160.         SERA_Baud,            Config->SerialConfig->BaudRate,
  161.         SERA_BreakTime,        Config->SerialConfig->BreakLength,
  162.         SERA_BitsPerChar,    Config->SerialConfig->BitsPerChar,
  163.         SERA_StopBits,        Config->SerialConfig->StopBits,
  164.         SERA_BufferSize,    Config->SerialConfig->SerialBufferSize,
  165.         SERA_Parity,        Config->SerialConfig->Parity,
  166.         SERA_Handshaking,    UseRTS_CTS ? Config->SerialConfig->HandshakingProtocol : HANDSHAKING_NONE,
  167.         SERA_HighSpeed,        Config->SerialConfig->HighSpeed,
  168.         SERA_Shared,        Config->SerialConfig->Shared,
  169.     TAG_DONE));
  170. }
  171.  
  172.     /* SendBreak():
  173.      *
  174.      *    Transmit a break signal.
  175.      */
  176.  
  177. VOID
  178. SendBreak()
  179. {
  180.     PushStatus(STATUS_BREAKING);
  181.  
  182.     DoSerialCmd(SDCMD_BREAK);
  183.  
  184.     PopStatus();
  185. }
  186.  
  187.     /* HangUp():
  188.      *
  189.      *    Hang up the line.
  190.      */
  191.  
  192. VOID
  193. HangUp()
  194. {
  195.     PushStatus(STATUS_HANGUP);
  196.  
  197.     StopSerialWrite();
  198.  
  199.         /* Are we to drop the DTR line
  200.          * before sending the hangup
  201.          * string?
  202.          */
  203.  
  204.     if(Config->ModemConfig->DropDTR)
  205.     {
  206.         if(!DropDTR(Config->SerialConfig->SerialDevice,Config->SerialConfig->UnitNumber))
  207.         {
  208.             DeleteSerial();
  209.  
  210.             if(!ShowRequest(Window,LocaleString(MSG_TERMMAIN_FAILED_TO_REOPEN_UNIT_TXT),LocaleString(MSG_TERMMAIN_IGNORE_QUIT_TXT),Config->SerialConfig->SerialDevice,Config->SerialConfig->UnitNumber))
  211.                 MainTerminated = TRUE;
  212.         }
  213.     }
  214.  
  215.         /* Transmit the hangup command. */
  216.  
  217.     if(Config->ModemConfig->ModemHangup[0] && !MainTerminated)
  218.         SerialCommand(Config->ModemConfig->ModemHangup);
  219.  
  220.         /* Reset to old status. */
  221.  
  222.     PopStatus();
  223. }
  224.  
  225.     /* CopyWriteFlags():
  226.      *
  227.      *    Update configuration with serial settings.
  228.      */
  229.  
  230. VOID
  231. CopyWriteFlags()
  232. {
  233.     ULONG    Baud,
  234.             BreakTime,
  235.             BitsPerChar,
  236.             StopBits,
  237.             BufferSize,
  238.             Parity,
  239.             Handshaking,
  240.             HighSpeed,
  241.             Shared;
  242.  
  243.     GetSerialWriteAttributes(
  244.         SERA_Baud,            &Baud,
  245.         SERA_BreakTime,        &BreakTime,
  246.         SERA_BitsPerChar,    &BitsPerChar,
  247.         SERA_StopBits,        &StopBits,
  248.         SERA_BufferSize,    &BufferSize,
  249.         SERA_Parity,        &Parity,
  250.         SERA_Handshaking,    &Handshaking,
  251.         SERA_HighSpeed,        &HighSpeed,
  252.         SERA_Shared,        &Shared,
  253.     TAG_DONE);
  254.  
  255.     Config->SerialConfig->BaudRate                = Baud;
  256.     Config->SerialConfig->BreakLength            = BreakTime;
  257.     Config->SerialConfig->BitsPerChar            = BitsPerChar;
  258.     Config->SerialConfig->StopBits                = StopBits;
  259.     Config->SerialConfig->SerialBufferSize        = BufferSize;
  260.     Config->SerialConfig->Parity                = Parity;
  261.     Config->SerialConfig->HandshakingProtocol    = Handshaking;
  262.     Config->SerialConfig->HighSpeed                = HighSpeed;
  263.     Config->SerialConfig->Shared                = Shared;
  264. }
  265.  
  266.     /* SerWriteVerbatim(APTR Buffer,LONG Size,BOOL Echo):
  267.      *
  268.      *    The `no fancy features' version of SerWrite().
  269.      */
  270.  
  271. VOID
  272. SerWriteVerbatim(APTR Buffer,LONG Size,BOOL Echo)
  273. {
  274.     if(XProtocolBase && (TransferBits & XPRS_USERMON))
  275.         Size = XProtocolUserMon(XprIO,Buffer,Size,Size);
  276.  
  277.     if(Size > 0)
  278.     {
  279.         if(Echo)
  280.             WriteAndProcess(Buffer,Size);
  281.         else
  282.             DoSerialWrite(Buffer,Size);
  283.  
  284.         BytesOut += Size;
  285.     }
  286. }
  287.  
  288.     /* SerWriteUpdate():
  289.      *
  290.      *    Choose the right data output routine for the job.
  291.      */
  292.  
  293. VOID
  294. SerWriteUpdate()
  295. {
  296.     if(SerWriteBypass)
  297.     {
  298.         if(XProtocolBase && (TransferBits & XPRS_USERMON))
  299.         {
  300.             SerWriteRoutine = (SERWRITE)WriteBypassUserMon;
  301.             SerWriteAndProcessRoutine = (SERWRITE)WriteAndProcessBypassUserMon;
  302.         }
  303.         else
  304.         {
  305.             SerWriteRoutine = (SERWRITE)WriteBypass;
  306.             SerWriteAndProcessRoutine = (SERWRITE)WriteAndProcessBypass;
  307.         }
  308.     }
  309.     else
  310.     {
  311.         if(XProtocolBase && (TransferBits & XPRS_USERMON))
  312.         {
  313.             SerWriteRoutine = (SERWRITE)WriteUserMon;
  314.             SerWriteAndProcessRoutine = (SERWRITE)WriteAndProcessUserMon;
  315.         }
  316.         else
  317.         {
  318.             SerWriteRoutine = (SERWRITE)WriteDirect;
  319.             SerWriteAndProcessRoutine = (SERWRITE)WriteAndProcess;
  320.         }
  321.     }
  322. }
  323.  
  324.     /* SerWrite(APTR Buffer,LONG Size):
  325.      *
  326.      *    Send a number of bytes across the serial line.
  327.      */
  328.  
  329. VOID
  330. SerWrite(APTR Buffer,LONG Size)
  331. {
  332.     if(Size < 0)
  333.         Size = strlen(Buffer);
  334.  
  335.     if(Size > 0)
  336.     {
  337.         if(RememberInput)
  338.         {
  339.             RememberInputText(Buffer,Size);
  340.  
  341.             if(((UBYTE *)Buffer)[Size - 1] == '\r' && RecordingLine)
  342.             {
  343.                 RememberSpill();
  344.  
  345.                 RecordingLine = FALSE;
  346.  
  347.                 RememberOutput = TRUE;
  348.                 RememberInput = FALSE;
  349.  
  350.                 CheckItem(MEN_RECORD_LINE,FALSE);
  351.             }
  352.         }
  353.         else
  354.         {
  355.             if(RememberOutput)
  356.             {
  357.                 RememberInputText(Buffer,Size);
  358.  
  359.                 RememberSpill();
  360.             }
  361.         }
  362.  
  363.         if(WriteRequest)
  364.         {
  365.             if(SendTable)
  366.             {
  367.                 struct TranslationHandle Handle;
  368.                 UBYTE TranslateData[256];
  369.  
  370.                     /* Set up for buffer translation. */
  371.  
  372.                 TranslateSetup(&Handle,Buffer,Size,TranslateData,sizeof(TranslateData),SendTable);
  373.  
  374.                     /* Full or half duplex? */
  375.  
  376.                 if(Config->SerialConfig->Duplex == DUPLEX_FULL)
  377.                 {
  378.                         /* Process the data... */
  379.  
  380.                     while(Size = TranslateBuffer(&Handle))
  381.                         (*SerWriteRoutine)(TranslateData,Size);
  382.                 }
  383.                 else
  384.                 {
  385.                     while(Size = TranslateBuffer(&Handle))
  386.                         (*SerWriteAndProcessRoutine)(TranslateData,Size);
  387.                 }
  388.             }
  389.             else
  390.             {
  391.                 if(Config->SerialConfig->Duplex == DUPLEX_FULL)
  392.                     (*SerWriteRoutine)(Buffer,Size);
  393.                 else
  394.                     (*SerWriteAndProcessRoutine)(Buffer,Size);
  395.             }
  396.         }
  397.     }
  398. }
  399.  
  400.     /* RestartSerial():
  401.      *
  402.      *    Restart read/write activity on the serial line.
  403.      */
  404.  
  405. VOID
  406. RestartSerial()
  407. {
  408.         /* Blow away the cache if there is anything left of it. */
  409.  
  410.     if(DataHold)
  411.     {
  412.         DataHold = NULL;
  413.  
  414.         UpdateSerialJob();
  415.     }
  416.  
  417.     StartSerialRead(&ReadChar,1);
  418. }
  419.  
  420.     /* ClearSerial():
  421.      *
  422.      *    Terminate all read/write activity on the serial line.
  423.      */
  424.  
  425. VOID
  426. ClearSerial()
  427. {
  428.         /* Blow away the cache if there is anything left of it. */
  429.  
  430.     if(DataHold)
  431.     {
  432.         DataHold = NULL;
  433.  
  434.         UpdateSerialJob();
  435.     }
  436.  
  437.     StopSerialRead();
  438.  
  439.     FlushSerialRead();
  440. }
  441.  
  442.     /* DeleteSerial():
  443.      *
  444.      *    Close the serial device and release all associated
  445.      *    resources.
  446.      */
  447.  
  448. VOID
  449. DeleteSerial()
  450. {
  451.     StopSerialRead();
  452.     StopSerialWrite();
  453.  
  454.     if(ReadRequest)
  455.     {
  456.         if(ReadRequest->IOSer.io_Device)
  457.         {
  458.             UBYTE Name[MAX_FILENAME_LENGTH];
  459.             struct Device *Device;
  460.  
  461.                 /* Unless the device was opened in shared */
  462.                 /* access mode we'll reset it here */
  463.  
  464.             if(!Config->SerialConfig->Shared)
  465.             {
  466.                 ReadRequest->IOSer.io_Command = CMD_RESET;
  467.  
  468.                 DoIO((struct IORequest *)ReadRequest);
  469.             }
  470.  
  471.                 /* Remember the device name, we'll need it after */
  472.                 /* closing time */
  473.  
  474.             LimitedStrcpy(sizeof(Name),Name,ReadRequest->IOSer.io_Device->dd_Library.lib_Node.ln_Name);
  475.  
  476.                 /* Close the device */
  477.  
  478.             CloseDevice((struct IORequest *)ReadRequest);
  479.  
  480.                 /* And remove it from memory */
  481.  
  482.             Forbid();
  483.  
  484.             if(Device = (struct Device *)FindName(&SysBase->DeviceList,Name))
  485.                 RemDevice(Device);
  486.  
  487.             Permit();
  488.         }
  489.  
  490.         DeleteIORequest(ReadRequest);
  491.         ReadRequest = NULL;
  492.     }
  493.  
  494.     if(WriteRequest)
  495.     {
  496.         DeleteIORequest(WriteRequest);
  497.         WriteRequest = NULL;
  498.     }
  499.  
  500.     if(WritePort)
  501.     {
  502.         DeleteMsgPort(WritePort);
  503.         WritePort = NULL;
  504.     }
  505.  
  506.     if(ReadPort)
  507.     {
  508.         DeleteMsgPort(ReadPort);
  509.         ReadPort = NULL;
  510.     }
  511.  
  512.     FreeVecPooled(ReadBuffer);
  513.     ReadBuffer = NULL;
  514.  
  515.     FreeVecPooled(HostReadBuffer);
  516.     HostReadBuffer = NULL;
  517.  
  518.     FreeVecPooled(StripBuffer);
  519.     StripBuffer = NULL;
  520.  
  521.     UnlockDevice();
  522.  
  523.     UpdateSerialJob();
  524. }
  525.  
  526.     /* GetSerialError(LONG Error,BOOL *Reset):
  527.      *
  528.      *    Return an error message for each possible serial device error.
  529.      */
  530.  
  531. STRPTR
  532. GetSerialError(LONG Error,BOOL *ResetPtr)
  533. {
  534.     BOOL Reset;
  535.     LONG ID;
  536.  
  537.     Reset    = FALSE;
  538.     ID        = -1;
  539.  
  540.     switch(Error)
  541.     {
  542.         case IOERR_BADLENGTH:
  543.         case IOERR_BADADDRESS:
  544.         case IOERR_SELFTEST:
  545.         case IOERR_OPENFAIL:
  546.  
  547.             ID = MSG_SERIAL_OPENFAILURE_TXT;
  548.             break;
  549.  
  550.         case SerErr_DevBusy:
  551.  
  552.             ID = MSG_SERIAL_ERROR_DEVBUSY_TXT;
  553.             break;
  554.  
  555.         case SerErr_BaudMismatch:
  556.  
  557.             Reset = TRUE;
  558.             ID = MSG_SERIAL_ERROR_BAUDMISMATCH_TXT;
  559.             break;
  560.  
  561.         case SerErr_BufErr:
  562.  
  563.             Reset = TRUE;
  564.             ID = MSG_SERIAL_ERROR_BUFERR_TXT;
  565.             break;
  566.  
  567.         case SerErr_InvParam:
  568.  
  569.             Reset = TRUE;
  570.             ID = MSG_SERIAL_ERROR_INVPARAM_TXT;
  571.             break;
  572.  
  573.         case SerErr_LineErr:
  574.  
  575.             ID = MSG_SERIAL_ERROR_LINEERR_TXT;
  576.             break;
  577.  
  578.         case SerErr_ParityErr:
  579.  
  580.             Reset = TRUE;
  581.             ID = MSG_SERIAL_ERROR_PARITYERR_TXT;
  582.             break;
  583.  
  584.         case SerErr_TimerErr:
  585.  
  586.             ID = MSG_SERIAL_ERROR_TIMERERR_TXT;
  587.             break;
  588.  
  589.         case SerErr_BufOverflow:
  590.  
  591.             Reset = TRUE;
  592.             ID = MSG_SERIAL_ERROR_BUFOVERFLOW_TXT;
  593.             break;
  594.  
  595.         case SerErr_NoDSR:
  596.  
  597.             ID = MSG_SERIAL_ERROR_NODSR_TXT;
  598.             break;
  599.  
  600.     /*    case SerErr_UnitBusy:    */
  601.         case IOERR_UNITBUSY:
  602.         case 16:
  603.  
  604.             ID = MSG_SERIAL_ERROR_UNIT_BUSY_TXT;
  605.             break;
  606.     }
  607.  
  608.     if(ID != -1)
  609.     {
  610.         if(ResetPtr)
  611.             *ResetPtr = Reset;
  612.  
  613.         return(LocaleString(ID));
  614.     }
  615.     else
  616.         return(NULL);
  617. }
  618.  
  619.     /* CreateSerial():
  620.      *
  621.      *    Create handles for the serial device and open it.
  622.      */
  623.  
  624. BOOL
  625. CreateSerial(STRPTR ErrorBuffer,LONG ErrorBufferSize)
  626. {
  627.     BYTE Error = 0;
  628.     LONG ID = -1;
  629.  
  630.         /* Try to lock the serial device driver if necessary */
  631.  
  632.     if(Config->SerialConfig->UseOwnDevUnit && !(Config->SerialConfig->Shared && Config->SerialConfig->NoODUIfShared))
  633.     {
  634.         if(!LockDevice(Config->SerialConfig->SerialDevice,Config->SerialConfig->UnitNumber,ErrorBuffer,ErrorBufferSize))
  635.             return(FALSE);
  636.     }
  637.  
  638.         /* Propagate the serial read buffer size to the translation routines */
  639.  
  640.     Update_CR_LF_Translation();
  641.  
  642.         /* Now allocate the required resources... */
  643.  
  644.     if(ReadBuffer = AllocVecPooled(Config->SerialConfig->SerialBufferSize,MEMF_ANY))
  645.     {
  646.         if(StripBuffer = AllocVecPooled(Config->SerialConfig->SerialBufferSize,MEMF_ANY))
  647.         {
  648.             if(XProtocolBase && (TransferBits & XPRS_HOSTNOWAIT))
  649.                 HostReadBuffer = AllocVecPooled(Config->SerialConfig->SerialBufferSize,MEMF_ANY);
  650.  
  651.             if(ReadPort = (struct MsgPort *)CreateMsgPort())
  652.             {
  653.                 if(ReadRequest = (struct IOExtSer *)CreateIORequest(ReadPort,sizeof(struct IOExtSer)))
  654.                 {
  655.                     if(WritePort = (struct MsgPort *)CreateMsgPort())
  656.                     {
  657.                         if(WriteRequest = (struct IOExtSer *)CreateIORequest(WritePort,sizeof(struct IOExtSer)))
  658.                         {
  659.                                 /* Unless the user doesn't want RTS/CTS handshaking */
  660.                                 /* we'll assume it should be enabled. This also concerns */
  661.                                 /* the RTS/CTS+DSR test mode which will also start */
  662.                                 /* with having RTS/CTS handshaking enabled. */
  663.  
  664.                             UseRTS_CTS = (BOOL)(Config->SerialConfig->HandshakingProtocol != HANDSHAKING_NONE);
  665.  
  666.                                 /* Set the default opening parameters */
  667.  
  668.                             SetSerialReadAttributes(
  669.                                 SERA_Baud,            Config->SerialConfig->BaudRate,
  670.                                 SERA_BreakTime,        Config->SerialConfig->BreakLength,
  671.                                 SERA_BitsPerChar,    Config->SerialConfig->BitsPerChar,
  672.                                 SERA_StopBits,        Config->SerialConfig->StopBits,
  673.                                 SERA_BufferSize,    Config->SerialConfig->SerialBufferSize,
  674.                                 SERA_Parity,        Config->SerialConfig->Parity,
  675.                                 SERA_Handshaking,    Config->SerialConfig->HandshakingProtocol,
  676.                                 SERA_HighSpeed,        Config->SerialConfig->HighSpeed,
  677.                                 SERA_Shared,        Config->SerialConfig->Shared,
  678.                             TAG_DONE);
  679.  
  680.                                 /* Open the device driver */
  681.  
  682.                             if(!(Error = OpenSerialDevice(Config->SerialConfig->SerialDevice,Config->SerialConfig->UnitNumber)))
  683.                             {
  684.                                     /* Should we perform a DSR signal test before */
  685.                                     /* proceeding? */
  686.  
  687.                                 if(Config->SerialConfig->HandshakingProtocol == HANDSHAKING_RTSCTS_DSR)
  688.                                 {
  689.                                         /* Now check if the DSR signal is enabled. */
  690.  
  691.                                     if(GetSerialStatus() & CIAF_COMDSR)
  692.                                     {
  693.                                             /* If this is the first time the driver gets initialized, */
  694.                                             /* skip the notification message and just drop the RTS/CTS */
  695.                                             /* handshaking bit. */
  696.  
  697.                                         if(FirstInvocation)
  698.                                             UseRTS_CTS = FALSE;
  699.                                         else
  700.                                         {
  701.                                             do
  702.                                             {
  703.                                                 if(!ShowRequest(Window,LocaleString(MSG_SERIAL_NO_DSR_SIGNAL_TXT),LocaleString(MSG_SERIAL_RETRY_CANCEL_TXT)))
  704.                                                     UseRTS_CTS = FALSE;
  705.                                             }
  706.                                             while(UseRTS_CTS && (GetSerialStatus() & CIAF_COMDSR));
  707.                                         }
  708.                                     }
  709.                                 }
  710.  
  711.                                     /* Update the driver data */
  712.  
  713.                                 ResetSerialRead();
  714.                                 ResetSerialWrite();
  715.  
  716.                                     /* Set the parameters */
  717.  
  718.                                 SetFlags();
  719.  
  720.                                     /* And ask for a byte */
  721.  
  722.                                 RestartSerial();
  723.  
  724.                                 UpdateSerialJob();
  725.  
  726.                                 return(TRUE);
  727.                             }
  728.                         }
  729.                     }
  730.                     else
  731.                         ID = MSG_SERIAL_FAILED_TO_CREATE_WRITE_PORT_TXT;
  732.                 }
  733.             }
  734.             else
  735.                 ID = MSG_SERIAL_FAILED_TO_CREATE_READ_PORT_TXT;
  736.         }
  737.     }
  738.  
  739.         /* If we get here something must be wrong. */
  740.  
  741.     DeleteSerial();
  742.  
  743.         /* If we got an open error, we'll try to make it into */
  744.         /* a readable description */
  745.  
  746.     if(Error != 0)
  747.     {
  748.         STRPTR String;
  749.  
  750.         if(!(String = GetSerialError(Error,NULL)))
  751.             String = LocaleString(MSG_SERIAL_ERROR_DEVBUSY_TXT);
  752.  
  753.         LimitedSPrintf(ErrorBufferSize,ErrorBuffer,String,Config->SerialConfig->SerialDevice,Config->SerialConfig->UnitNumber);
  754.     }
  755.     else
  756.     {
  757.             /* If no open error has occured a problem must have */
  758.             /* hit us before the device was ready to open. */
  759.             /* If the error message ID is negative we'll use the */
  760.             /* default message which indicates memory allocation */
  761.             /* problems. */
  762.  
  763.         if(ID == -1)
  764.             ID = MSG_SERIAL_NOT_ENOUGH_MEMORY_TXT;
  765.  
  766.         strcpy(ErrorBuffer,LocaleString(ID));
  767.     }
  768.  
  769.     return(FALSE);
  770. }
  771.  
  772.     /* ReconfigureSerial(struct Window *Window,struct SerialSettings *SerialConfig):
  773.      *
  774.      *    Reconfigure the serial driver according to the new
  775.      *    serial settings.
  776.      */
  777.  
  778. LONG
  779. ReconfigureSerial(struct Window *Window,struct SerialSettings *SerialConfig)
  780. {
  781.     LONG Success = RECONFIGURE_NOCHANGE;
  782.  
  783.         /* Are new settings to be installed or have they already */
  784.         /* been copied to the correct locations? */
  785.  
  786.     if(CompareConfigEntries(Config->SerialConfig,SerialConfig ? SerialConfig : PrivateConfig->SerialConfig,PREF_SERIAL))
  787.     {
  788.         BOOL SameDevice = TRUE;
  789.  
  790.             /* Any new data to swap in? */
  791.  
  792.         if(SerialConfig)
  793.         {
  794.                 /* Store the previous settings. */
  795.  
  796.             SaveConfig(Config,PrivateConfig);
  797.  
  798.                 /* Install the new settings */
  799.  
  800.             PutConfigEntry(Config,SerialConfig,PREF_SERIAL);
  801.         }
  802.  
  803.             /* Any device name or unit number change? */
  804.  
  805.         if(strcmp(PrivateConfig->SerialConfig->SerialDevice,Config->SerialConfig->SerialDevice) || PrivateConfig->SerialConfig->UnitNumber != Config->SerialConfig->UnitNumber || PrivateConfig->SerialConfig->UseOwnDevUnit != Config->SerialConfig->UseOwnDevUnit)
  806.             SameDevice = FALSE;
  807.  
  808.             /* Handshaking mode changed? */
  809.  
  810.         if((PrivateConfig->SerialConfig->HandshakingProtocol == HANDSHAKING_NONE && Config->SerialConfig->HandshakingProtocol != HANDSHAKING_NONE) || (PrivateConfig->SerialConfig->HandshakingProtocol != HANDSHAKING_NONE && Config->SerialConfig->HandshakingProtocol == HANDSHAKING_NONE))
  811.             SameDevice = FALSE;
  812.  
  813.             /* Did the ODU options change? */
  814.  
  815.         if(PrivateConfig->SerialConfig->NoODUIfShared != Config->SerialConfig->NoODUIfShared && Config->SerialConfig->Shared)
  816.             SameDevice = FALSE;
  817.  
  818.             /* Is the device currently closed, i.e. should we open it? */
  819.  
  820.         if(!ReadRequest)
  821.             SameDevice = FALSE;
  822.  
  823.             /* Stop any IO activity. */
  824.  
  825.         ClearSerial();
  826.  
  827.             /* No dramatic changes? Simply change the parameters. */
  828.  
  829.         if(SameDevice)
  830.         {
  831.             LONG Error;
  832.  
  833.                 /* Did the buffer size change? */
  834.  
  835.             if(PrivateConfig->SerialConfig->SerialBufferSize != Config->SerialConfig->SerialBufferSize)
  836.             {
  837.                 STRPTR NewReadBuffer;
  838.                 STRPTR NewStripBuffer;
  839.  
  840.                     /* Allocate two new buffers */
  841.  
  842.                 NewReadBuffer    = AllocVecPooled(Config->SerialConfig->SerialBufferSize,MEMF_ANY);
  843.                 NewStripBuffer    = AllocVecPooled(Config->SerialConfig->SerialBufferSize,MEMF_ANY);
  844.  
  845.                     /* Did we get both? */
  846.  
  847.                 if(NewReadBuffer && NewStripBuffer)
  848.                 {
  849.                         /* Release the old buffers */
  850.  
  851.                     FreeVecPooled(ReadBuffer);
  852.                     FreeVecPooled(StripBuffer);
  853.  
  854.                         /* And put the new ones in */
  855.  
  856.                     ReadBuffer    = NewReadBuffer;
  857.                     StripBuffer    = NewStripBuffer;
  858.                 }
  859.                 else
  860.                 {
  861.                         /* Release whatever we had allocated */
  862.  
  863.                     FreeVecPooled(NewReadBuffer);
  864.                     FreeVecPooled(NewStripBuffer);
  865.  
  866.                         /* And change back to the old buffer size */
  867.  
  868.                     Config->SerialConfig->SerialBufferSize = PrivateConfig->SerialConfig->SerialBufferSize;
  869.                 }
  870.             }
  871.  
  872.                 /* Propagate the buffer size to the translation routines */
  873.  
  874.             Update_CR_LF_Translation();
  875.  
  876.                 /* Use new parameters */
  877.  
  878.             if(Error = SetFlags())
  879.             {
  880.                 UBYTE LocalBuffer[256];
  881.                 STRPTR String;
  882.                 BOOL Reset;
  883.  
  884.                     /* Get the error message. */
  885.  
  886.                 if(!(String = GetSerialError(Error,&Reset)))
  887.                     String = LocaleString(MSG_SERIAL_ERROR_DEVBUSY_TXT);
  888.  
  889.                     /* Build the device name/unit number string. */
  890.  
  891.                 LimitedSPrintf(sizeof(LocalBuffer),LocalBuffer,String,Config->SerialConfig->SerialDevice,Config->SerialConfig->UnitNumber);
  892.  
  893.                     /* Display the error requester. */
  894.  
  895.                 ShowRequest(Window,LocaleString(MSG_GLOBAL_TERM_HAS_A_PROBLEM_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),LocalBuffer);
  896.  
  897.                     /* Is a serial driver reset required? */
  898.  
  899.                 if(Reset)
  900.                 {
  901.                         /* Execute the reset command. */
  902.  
  903.                     DoSerialCmd(CMD_RESET);
  904.  
  905.                         /* Copy the serial driver settings */
  906.                         /* to the global configuration. */
  907.  
  908.                     CopyWriteFlags();
  909.  
  910.                         /* Also set the read request driver flags */
  911.  
  912.                     SetFlags();
  913.                 }
  914.             }
  915.  
  916.                 /* Restart read request */
  917.  
  918.             RestartSerial();
  919.         }
  920.         else
  921.         {
  922.             UBYTE LocalBuffer[256];
  923.  
  924.                 /* Shut down the serial device driver */
  925.  
  926.             DeleteSerial();
  927.  
  928.                 /* Reinitialize the serial device driver */
  929.  
  930.             if(!CreateSerial(LocalBuffer,sizeof(LocalBuffer)))
  931.             {
  932.                     /* Display the error requester */
  933.  
  934.                 ShowRequest(Window,LocaleString(MSG_GLOBAL_TERM_HAS_A_PROBLEM_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),LocalBuffer);
  935.  
  936.                     /* That didn't work */
  937.  
  938.                 Success = RECONFIGURE_FAILURE;
  939.             }
  940.         }
  941.     }
  942.  
  943.     return(Success);
  944. }
  945.  
  946.     /* ReopenSerial():
  947.      *
  948.      *    Reopen the serial driver.
  949.      */
  950.  
  951. VOID
  952. ReopenSerial()
  953. {
  954.     BOOL SerialClosed = TRUE;
  955.     UBYTE LocalBuffer[256];
  956.  
  957.     do
  958.     {
  959.         if(CreateSerial(LocalBuffer,sizeof(LocalBuffer)))
  960.             SerialClosed = FALSE;
  961.         else
  962.         {
  963.             switch(ShowRequest(Window,LocaleString(MSG_GLOBAL_TERM_HAS_A_PROBLEM_TXT),LocaleString(MSG_TERMMAIN_RETRY_IGNORE_QUIT_TXT),LocalBuffer))
  964.             {
  965.                 case 0:
  966.  
  967.                     MainTerminated = TRUE;
  968.                     break;
  969.  
  970.                 case 2:
  971.  
  972.                     SerialClosed = FALSE;
  973.                     break;
  974.             }
  975.         }
  976.     }
  977.     while(SerialClosed && !MainTerminated);
  978. }
  979.  
  980.     /* HandleSerialJob():
  981.      *
  982.      *    Handle the data coming in from the serial line.
  983.      */
  984.  
  985. BOOL
  986. HandleSerialJob(JobNode *UnusedJob)
  987. {
  988.     BOOL MoreData;
  989.  
  990.     if(HostReadBuffer)
  991.     {
  992.         LONG Length = XProtocolHostMon(XprIO,HostReadBuffer,0,SerialBufferSize);
  993.  
  994.         if(Translate_CR_LF && Length > 0)
  995.             Length = (*Translate_CR_LF)(HostReadBuffer,Length);
  996.  
  997.         if(Length > 0)
  998.         {
  999.             ConProcess(HostReadBuffer,Length);
  1000.  
  1001.             if(Get_xOFF())
  1002.                 return(FALSE);
  1003.         }
  1004.  
  1005.         MoreData = TRUE;
  1006.     }
  1007.     else
  1008.         MoreData = FALSE;
  1009.  
  1010.         /* Any news? */
  1011.  
  1012.     if(CheckSerialRead())
  1013.     {
  1014.             /* Terminate the read request properly. */
  1015.  
  1016.         if(!WaitSerialRead())
  1017.         {
  1018.             ULONG Length;
  1019.  
  1020.                 /* We got another byte. */
  1021.  
  1022.             ReadBuffer[0] = ReadChar;
  1023.  
  1024.                 /* Check if there is anything waiting to be read. */
  1025.  
  1026.             if(Length = GetSerialWaiting())
  1027.             {
  1028.                 ULONG MaxSize;
  1029.  
  1030.                     /* This is how many characters fill still fit into
  1031.                      * the read buffer.
  1032.                      */
  1033.  
  1034.                 MaxSize = SerialBufferSize - 1;
  1035.  
  1036.                     /* Check if there is more data waiting
  1037.                      * than will fit into the buffer.
  1038.                      */
  1039.  
  1040.                 if(Length > MaxSize)
  1041.                     Length = MaxSize;
  1042.  
  1043.                     /* Check if there is more data waiting than
  1044.                      * the serial quantum allows.
  1045.                      */
  1046.  
  1047.                 if(Length > Config->SerialConfig->Quantum)
  1048.                     Length = Config->SerialConfig->Quantum;
  1049.  
  1050.                     /* Read the data still waiting. */
  1051.  
  1052.                 if(DoSerialRead(&ReadBuffer[1],Length))
  1053.                     Length = 0;
  1054.             }
  1055.  
  1056.                 /* One byte was added earlier. */
  1057.  
  1058.             Length++;
  1059.  
  1060.                 /* Process the data. */
  1061.  
  1062.             BytesIn += Length;
  1063.  
  1064.             (*ConTransfer)(ReadBuffer,Length);
  1065.         }
  1066.  
  1067.             /* If something is in the cache, don't overwrite
  1068.              * it by requesting another byte. Serial I/O
  1069.              * processing will be restarted when the cache
  1070.              * gets drained.
  1071.              */
  1072.  
  1073.         if(!DataHold && ProcessIO)
  1074.         {
  1075.                 /* Yes, there is more to come. */
  1076.  
  1077.             MoreData = TRUE;
  1078.  
  1079.             StartSerialRead(&ReadChar,1);
  1080.         }
  1081.     }
  1082.  
  1083.     return(MoreData);
  1084. }
  1085.  
  1086.     /* UpdateSerialJob():
  1087.      *
  1088.      *    Either activate or suspend the serial I/O job.
  1089.      */
  1090.  
  1091. VOID
  1092. UpdateSerialJob()
  1093. {
  1094.     ULONG Mask;
  1095.  
  1096.     if(!Get_xOFF() && ReadPort && ProcessIO)
  1097.         Mask = SIG_SERIAL;
  1098.     else
  1099.         Mask = NULL;
  1100.  
  1101.     if(Mask)
  1102.     {
  1103.         if(DataHold)
  1104.         {
  1105.             Mask = NULL;
  1106.  
  1107.             ActivateJob(MainJobQueue,SerialCacheJob);
  1108.         }
  1109.         else
  1110.             SuspendJob(MainJobQueue,SerialCacheJob);
  1111.     }
  1112.  
  1113.     UpdateJob(MainJobQueue,SerialJob,Mask);
  1114.  
  1115.         /* Now pick the right simplified access routines
  1116.          * for the job.
  1117.          */
  1118.  
  1119.     if(DataHold)
  1120.     {
  1121.         SerialWaitForData    = SerialCacheWaitForData;
  1122.         SerialGetWaiting    = SerialCacheGetWaiting;
  1123.         SerialRead            = SerialCacheRead;
  1124.     }
  1125.     else
  1126.     {
  1127.         SerialWaitForData    = SerialStdWaitForData;
  1128.         SerialGetWaiting    = SerialStdGetWaiting;
  1129.         SerialRead            = SerialStdRead;
  1130.     }
  1131. }
  1132.  
  1133.     /* HandleSerialCacheJob(JobNode *UnusedJob):
  1134.      *
  1135.      *    Does what HandleSerialJob() does, but picks the
  1136.      *    data from the cache.
  1137.      */
  1138.  
  1139. BOOL
  1140. HandleSerialCacheJob(JobNode *UnusedJob)
  1141. {
  1142.     STRPTR    Data = DataHold;
  1143.     LONG    Size = DataSize;
  1144.  
  1145.         /* These two are no longer valid. */
  1146.  
  1147.     DataHold = NULL;
  1148.     DataSize = 0;
  1149.  
  1150.         /* If there was anything in the buffer,
  1151.          * process it.
  1152.          */
  1153.  
  1154.     if(Size > 0)
  1155.         (*ConTransfer)(Data,Size);
  1156.  
  1157.     RestartSerial();
  1158.  
  1159.     UpdateSerialJob();
  1160.  
  1161.     return(TRUE);
  1162. }
  1163.  
  1164.  
  1165. /**********************************************************************/
  1166.  
  1167.  
  1168.     /* SerialStdWaitForData(ULONG OtherBits):
  1169.      *
  1170.      *    Wait for new data to arrive or other events to
  1171.      *    take place.
  1172.      */
  1173.  
  1174. ULONG
  1175. SerialStdWaitForData(ULONG OtherBits)
  1176. {
  1177.     return(Wait(SIG_SERIAL | OtherBits));
  1178. }
  1179.  
  1180.     /* SerialCacheWaitForData(ULONG OtherBits):
  1181.      *
  1182.      *    Checks if other events took place and always flag
  1183.      *    new serial data to be available.
  1184.      */
  1185.  
  1186. ULONG
  1187. SerialCacheWaitForData(ULONG OtherBits)
  1188. {
  1189.     return((SetSignal(0,OtherBits) & OtherBits) | SIG_SERIAL);
  1190. }
  1191.  
  1192.     /* SerialStdGetWaiting():
  1193.      *
  1194.      *    Get the number of bytes still waiting to be read.
  1195.      */
  1196.  
  1197. ULONG
  1198. SerialStdGetWaiting()
  1199. {
  1200.     return(GetSerialWaiting());
  1201. }
  1202.  
  1203.     /* SerialCacheGetWaiting():
  1204.      *
  1205.      *    Return the number of bytes still in the cache and
  1206.      *    the number of bytes waiting in the serial read
  1207.      *    buffer.
  1208.      */
  1209.  
  1210. ULONG
  1211. SerialCacheGetWaiting()
  1212. {
  1213.     return(DataSize + SerialStdGetWaiting());
  1214. }
  1215.  
  1216.     /* SerialStdRead(UBYTE *Buffer,LONG Len):
  1217.      *
  1218.      *    Reads a number of bytes from the serial line and
  1219.      *    puts them into the buffer. This routine assumes a
  1220.      *    read request had been queued earlier. It waits
  1221.      *    for the queued request to terminate, grabs the
  1222.      *    character that was read and fills the remaining
  1223.      *    buffer with the data to follow. Eventually, the
  1224.      *    read request gets queued again.
  1225.      */
  1226.  
  1227. LONG
  1228. SerialStdRead(UBYTE *Buffer,LONG Len)
  1229. {
  1230.     LONG Total;
  1231.  
  1232.         /* Wait for the read request to terminate. */
  1233.  
  1234.     WaitSerialRead();
  1235.  
  1236.         /* Put the byte into the buffer. */
  1237.  
  1238.     *Buffer++ = ReadChar;
  1239.     Len--;
  1240.  
  1241.         /* So far, one byte was read. */
  1242.  
  1243.     Total = 1;
  1244.  
  1245.         /* Any more data requested? */
  1246.  
  1247.     if(Len > 0)
  1248.     {
  1249.             /* Read the rest. */
  1250.  
  1251.         if(!DoSerialRead(Buffer,Len))
  1252.             Total += Len;
  1253.     }
  1254.  
  1255.         /* Restart the read request. */
  1256.  
  1257.     StartSerialRead(&ReadChar,1);
  1258.  
  1259.         /* Return the number of bytes read so far. */
  1260.  
  1261.     return(Total);
  1262. }
  1263.  
  1264.     /* SerialCacheRead(UBYTE *Buffer,LONG Size):
  1265.      *
  1266.      *    Read a number of bytes from the cache and the
  1267.      *    serial buffer. Switch back to normal operation
  1268.      *    if the cache is exhausted.
  1269.      */
  1270.  
  1271. LONG
  1272. SerialCacheRead(UBYTE *Buffer,LONG Size)
  1273. {
  1274.     LONG Total;
  1275.  
  1276.         /* Nothing has been read yet. */
  1277.  
  1278.     Total = 0;
  1279.  
  1280.         /* Check if there is anything left in the cache. */
  1281.  
  1282.     if(DataSize > 0)
  1283.     {
  1284.         LONG Count;
  1285.  
  1286.             /* If there is more data in the cache than
  1287.              * requested, just read the requested number
  1288.              * of bytes from it.
  1289.              */
  1290.  
  1291.         if(DataSize > Size)
  1292.             Count = Size;
  1293.         else
  1294.             Count = DataSize;
  1295.  
  1296.             /* Copy the data from the cache into the buffer. */
  1297.  
  1298.         CopyMem(DataHold,Buffer,Count);
  1299.  
  1300.             /* This is how many bytes went into the buffer so far. */
  1301.  
  1302.         Total    += Count;
  1303.  
  1304.             /* Update the buffer data. */
  1305.  
  1306.         Buffer    += Count;
  1307.         Size    -= Count;
  1308.  
  1309.             /* Update the cache data. */
  1310.  
  1311.         DataHold += Count;
  1312.         DataSize -= Count;
  1313.     }
  1314.  
  1315.         /* If no data is left in the cache, switch the read routines
  1316.          * back to the standard versions. This is done inside
  1317.          * RestartSerial().
  1318.          */
  1319.  
  1320.     if(DataSize == 0)
  1321.         RestartSerial();
  1322.  
  1323.         /* If there is still data to be read, read it from the standard
  1324.          * channel, otherwise return the number of bytes already read.
  1325.          */
  1326.  
  1327.     if(Size > 0)
  1328.         return(Total + SerialStdRead(Buffer,Size));
  1329.     else
  1330.         return(Total);
  1331. }
  1332.